﻿
/// <reference path="Component.js" />
/// <reference path="_namespace.js" />
/// <reference path="MenuItemDisplayFlags.js" />

/*****************************************************************************
Ajax library class definition. Kevin Robinson 2006.
Class: ajax.components.ConfigurationManager

This class is designed to be subclassed, thus can be thought of as "abstract"
since, by default it knows nothing of the object it is being used within.

Any subclasses would need to override (at least)
- exportConfiguration
- importConfiguration
- createConfigurationMenu

/*****************************************************************************/


ajax.lang.addNamespace("ajax.components");
ajax.lang.imports("ajax.components.MenuItemDisplayFlags");

//-----------------------------------------------------------------------------
ajax.components.ConfigurationManager = function(doc) // Cibstructor
{
    ajax.components.ConfigurationManager.superConstructor.call(this, doc);
    
    // These 2 properties are for the Config menu
    this.configurationMenu = null;
    this.configureTriggers = new Array();
    
    // The rest of these are for persisting data back to the server.
    this.configureSave      = null;  // ContentLoader
    this.configureLoad      = null;  // ContentLoader
    // By wiring up this event router, the load & save HTTP requests have a default target
    // to callback to, and the default handler's are run. Most clients would not need anything else.
    // But if they did then this handler could be removed and replaced with other custom callbacks.
    this.getEvent(this.window, "onConfigureLoad").addListener(this.onConfigureLoadHandler);
    this.getEvent(this.window, "onConfigureSave").addListener(this.onConfigureSaveHandler);
    // Default objects to export & import
    this.exported = new Object();
    this.imported = new Object();
}

//-----------------------------------------------------------------------------
ajax.lang.extend("ajax.components.ConfigurationManager", "ajax.components.Component"); // Inherit
//-----------------------------------------------------------------------------


//-----------------------------------------------------------------------------
// These 2 methods should be overridden to cherry pick what to export & import
// OVERRIDE 1
ajax.components.ConfigurationManager.prototype.exportConfiguration = function()
{
    // this is where custom properties can be cherry picked from any object into the "this.exported" object for saving
}

//-----------------------------------------------------------------------------
// OVERRIDE 2
ajax.components.ConfigurationManager.prototype.importConfiguration = function()
{
    // This is where custom properties can be imported from the "this.imported" object
}

//-----------------------------------------------------------------------------
// This menthod should be overridden to provide a relevant menu for the object
// OVERRIDE 3
ajax.components.ConfigurationManager.prototype.createConfigurationMenu = function()
{
    /*
    Typical things to do here:
    1) define self closure.
    2) Create Menu
    this.configurationMenu = ajax.lang.safeNew("ajax.components.Menu", this.doc, "", 200, 120);
    
    2) Create function handlers for each option
    var onEnabledSelectDelegate = function(e)
    {   
        ajax.debug.Output.writeLn("You clicked on the Enabled Option: " + this.checked);
        self.configurationMenu.hide();
    }
    
    3) Create Menu Items themselves
    var displayFlags = ajax.components.MenuItemDisplayFlags;
    var flags = displayFlags.Image | displayFlags.Text | displayFlags.Checkbox;
    
    var item   = ajax.lang.safeNew("ajax.components.MenuItem",
        this.doc, "Text here", "", "EXAMPLE", null, flags, this.extendedProperties.enabled);
        
    4) Attach event handlers
    item.getEvent(this.window, "onSelected").addListener(onEnabledSelectDelegate);   
    
    5) Attach Items to menu
    this.configurationMenu.addMenuItem(item);       
    
    6) Add a delegate to the document mouseup to hide the menu
    ajax.lang.getEvent(this.window, this.doc, "onmouseup").addListener(function(e)
        {
            self.configurationMenu.hide();
        }
    );
    
    And that's it. Following is a simple menu to show something as default
    */ 
    

    // Create menu, add items, add handlers for the items, add (document level) handler to hide menu.
    this.configurationMenu = ajax.lang.safeNew("ajax.components.Menu", this.doc, "", 200, 100);
    this.configurationMenu.animated = true;
    this.configurationMenu.setWideBackground(true);
    
    var onConfigurationSelectDelegate = function(e)
    {
        alert("You clicked " + this);
        e.cancelBubble = true;
        return false;
    };
    
    var items = ["Configuration Menu", "goes here", "-", "Enabled"];
    var displayFlags = ajax.components.MenuItemDisplayFlags;
    
    for (var i = 0; i < items.length; i++)
    {    
        var item = ajax.lang.safeNew("ajax.components.MenuItem", 
            this.doc, items[i], "", "KEY_" + i, null, displayFlags.Image | displayFlags.Checkbox, true);            
            
        this.configurationMenu.addMenuItem(item);
        item.getEvent(this.window, "onSelected").addListener(onConfigurationSelectDelegate);
    }
    
    // Add a delegate to the document click to hide this menu
    var self = this;
    ajax.lang.getEvent(this.window, this.doc, "onmouseup").addListener(function(){ self.configurationMenu.hide(); });
    
}

//-----------------------------------------------------------------------------
ajax.components.ConfigurationManager.prototype.toString = function()
{
    return "ajax.components.ConfigurationManager";
}





//-----------------------------------------------------------------------------
// This method probably doesn't need to be overridden. One reason to do so would be to 
// update menu items (checked) if somehow the base data has changed by another process (than through the menu).
ajax.components.ConfigurationManager.prototype.showConfigurationMenu = function(e)
{    
    // Get a handle back to ourself from the object clicked
    var self = this.configureObject;
    if (self.configurationMenu == null)
        self.createConfigurationMenu(); 
    // Show the menu hanging off this object
    self.configurationMenu.show(null, null, this);                   
}



//-----------------------------------------------------------------------------
// These two methods would probably NOT be overridden as they are so standard.
// - they just set & get data from the import & export objects. 
// They are wired in the constructor to listen for the Load(ed) and save(d)
// events coming back from the Content Loaders.
ajax.components.ConfigurationManager.prototype.onConfigureLoadHandler = function(e)
{
    // The options have now been loaded into this.imported
    var text = e.responseText;
    if (text != "")
    {
        this.imported = text.toJsonObject();
        this.importConfiguration(); // This would be overridden with 
        ajax.debug.Output.writeLn("Loaded " + this + " config: " + text);
    }
    else    
        ajax.debug.Output.writeLn(this + ".onConfigureLoadHandler was passed a blank string from the server.");        
}

//-----------------------------------------------------------------------------
ajax.components.ConfigurationManager.prototype.onConfigureSaveHandler = function(e)
{        
    var text = e.responseText;
    if (text != "")
    {
        this.imported = text.toJsonObject();
        this.importConfiguration();  
        ajax.debug.Output.writeLn("Saved " + this + " config: " + text);      
    }
    else
        ajax.debug.Output.writeLn(this + ".onConfigureSaveHandler was passed a blank string from the server."); 
}



//-----------------------------------------------------------------------------
// I see no reason to need to override these methods
ajax.components.ConfigurationManager.prototype.enableConfigureLoad = function(url, loadParams)
{
    this.configureLoad = ajax.lang.safeNew("ajax.net.ContentLoader", this, this.onConfigureLoad, null, url, "POST", loadParams);
}

//-----------------------------------------------------------------------------
ajax.components.ConfigurationManager.prototype.enableConfigureSave = function(url, saveParams)
{
    this.configureSave = ajax.lang.safeNew("ajax.net.ContentLoader", this, this.onConfigureSave, null, url, "POST", saveParams);    
}

//-----------------------------------------------------------------------------
ajax.components.ConfigurationManager.prototype.loadConfiguration = function()
{
    if (!this.configureLoad)
        return;
    this.configureLoad.sendRequest();
}

//-----------------------------------------------------------------------------
ajax.components.ConfigurationManager.prototype.saveConfiguration = function()
{
    // Export required data
    this.exportConfiguration();    
    
    if (!this.configureSave)
        return;
        
    // Get JSON from object (without functions)
    var json = this.exported.toJsonString(false);
       
    // this will fire the this.onConfigureSaveDelegate, which will route the event out to anyone interested.
    this.configureSave.sendRequest("json=" + escape(json));
}

//-----------------------------------------------------------------------------
ajax.components.ConfigurationManager.prototype.addConfigureTrigger = function(obj)
{
    // Add without duplicate
    this.configureTriggers.append(obj, true);  
    
    // add us as the configureObject
    obj.configureObject = this;
    
    // add an event delegate to bring up the configuration menu 
    ajax.lang.getEvent(this.window, obj, "onclick").addListener(this.showConfigurationMenu);
}

//-----------------------------------------------------------------------------
ajax.components.ConfigurationManager.prototype.removeConfigureTrigger = function(obj)
{
    // remove the trigger obj
    this.configureTriggers.remove(obj);
    
    // Remove us
    obj.configureObject = null;
    
    // Remove delegate
    ajax.lang.getEvent(this.window, obj, "onclick").removeListener(this.showConfigurationMenu);
}

//-----------------------------------------------------------------------------
ajax.components.ConfigurationManager.prototype.toClassName = function()
{
    return ajax.lang.getClassName("ajax.components.ConfigurationManager");
}

//-----------------------------------------------------------------------------
ajax.components.ConfigurationManager.cast = function(obj)
{///<returns type="ajax.components.ConfigurationManager"/>
    return obj
}
